home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: display.c,v 0.91 1994/02/20 00:52:56 zhao Pre-Release $
- *
- *. This file is part of BIT shareware package. After the two weeks of
- * free evaluation period, you are encouraged (required) to register
- * your copy for a small registration fee, which is $35 for personal use
- * and $50 for commercial, government and institutional use.
- *
- * Copyright(c) 1993, 1994 by T.C. Zhao.
- * All rights reserved.
- *
- * Permission to use, copy, and distribute this software in its entirety
- * for non-commercial purposes is hereby granted, provided that the
- * above shareware and copyright notices and this permission notice
- * appear in all copies and their documentation.
- *
- * This software may be modified for your own use, but modified versions
- * may not be distributed without prior consent of the author.
- *
- * This software is provided "as is" without expressed or implied
- * warranty of any kind.
- *
- *.
- *
- * Display image defined in the image structure. Code is geared for maximum
- * speed. Also, some misc. routines that does mode settting and screen
- * clearing.
- *
- * Area bounded by im->{xi,yi,xf,yf} are the (true) image locations relative to
- * window. In the case where the image is larger than window, part of image
- * will be invisible (outside the viewing area). To speed up display, pxi,
- * pyi, pxf, pyf are guaranteed to be within the window even if image is
- * larger than window and degenerates into im->{xi,yi,xf,yf} if image is
- * smaller than window. px0 and py0 indicate the offset into the raster from
- * where the image starts, e.g., if displaying a pixel at (x,y), image
- * should be starting from (image + (y+py0) * width + x+px0). The other uses
- * of pxi,pyi etc. are when the image is panned, and part of the image is
- * invisible.
- *
- * The following relation MUST holds for panning etc.
- *
- * im->xf + im->xoff2 - (im->xi + im->xoff2) + 1 == Min(win_w, im->w);
- *
- * Note: for rectwrite, the screen localtions are specified by the parameters
- * and therefore, the x offset equals x-pxi+im->xoff1.
- *
- */
- #if !defined(lint) && defined(F_ID)
- char *id_dis = "$Id: display.c,v 0.91 1994/02/20 00:52:56 zhao Pre-Release $";
- #endif
-
- #include "bit.h"
- #include "extern.h"
- #include "dmalloc.h"
-
- /*******************************************************************
- * On some machines (4.0.5H ?), if the image is larger than the physical
- * screen, colormapped image will not display correctly.
- * Define PWRITE_BUG to enable workaround code
- *
- * To workaround code does not work either, something is wrong
- * with bit ....
- *******************************************************************/
- #define NO_PWRITE_BUG
-
- #ifndef NO_PWRITE_BUG
- #define PWRITE_BUG
- #endif
-
- /*****************************************************************
- * Note that ALL windows under BIT process have the same display mode
- * FORM window is not considered to be part of BIT process because
- * it takes care of its own redraws
- *******************************************************************/
-
- /********************** Local variables ***************************/
-
- static int rgbmode; /* current window mode */
- static short bkindex = BKINDEX; /* background color in CI mode */
- static rgba_t bkcolor; /* bkcolor in RGB mode */
- static int bkr, bkg, bkb; /* r,g,b for BK */
-
- /********************************************************
- * Set background color, but don't activate
- ********************************************************/
-
- void
- set_bk_color(rgba_t p)
- {
- bkcolor = p;
- CPACK2RGB(p, bkr, bkg, bkb);
- }
-
- /********************************************************
- * Choose display mode according to image type and hardware
- * characteristics.
- ********************************************************/
-
- #include "gl/get.h"
-
- /*******************************************************************
- * Switch current display mode to RGB, also matching doublebuffer
- * request.
- ******************************************************************/
- void
- set_rgb_mode(void)
- {
- int mode = getdisplaymode();
-
- /* re-config if mode mismatch or double/single buffer mismtach */
- if (!((mode == DMRGB && !double_buf) ||
- (mode == DMRGBDOUBLE && double_buf)))
- {
-
- M_info("Display", "Switching to RGBmode");
-
- RGBmode();
- (double_buf ? doublebuffer : singlebuffer) ();
- gconfig();
- rgbmode = 1;
- clear_screen(win_id, 1);
- }
- }
-
- void
- set_cmap_mode(void)
- {
- int mode = getdisplaymode();
-
- if (!((mode == DMSINGLE && !double_buf) ||
- (mode == DMDOUBLE && double_buf)))
- {
-
- M_info("Display", "Switching to CMAPmode");
-
- cmode();
- (double_buf ? doublebuffer : singlebuffer) ();
- gconfig();
-
- rgbmode = 0;
- clear_screen(win_id, 1);
- }
- }
-
- void
- set_display_mode(IPTR im)
- {
- CMPTR map = im->cmap;
-
- set_current_window(win_id);
-
- if (IS_CPACK(im))
- {
- set_rgb_mode();
- }
- else
- {
- set_cmap_mode();
- /* writemask(im->cmap->colors-1); */
- set_cmap(map);
- }
-
- }
-
- /*********************************************************
- * Clear current window
- *********************************************************/
-
- static void
- clear_it(void)
- {
- if (rgbmode)
- cpack(bkcolor);
- else
- {
- mapcolor(bkindex, bkr, bkg, bkb);
- color(bkindex);
- }
- clear();
- }
-
- /************************************************************
- * Clear specified window
- ************************************************************/
- void
- clear_screen(long win, int show)
- {
- long owin = winget();
- int dispmode = rgbmode;
-
- set_current_window(win);
- reshapeviewport();
- rgbmode = getdisplaymode();
- rgbmode = (rgbmode == DMRGB || rgbmode == DMRGBDOUBLE);
- clear_it();
- rgbmode = dispmode;
-
- if (show && double_buf)
- {
- swapbuffers();
- clear_it();
- }
-
- set_current_window(owin);
-
- }
-
- /*****************************************************************
- * Clear the region between rectangle r1 and r2.
- *****************************************************************/
- void
- clear_between_rect(const Rect_t * r1, const Rect_t * r2)
- {
- int xf1 = r1->x + r1->w - 1;
- int yf1 = r1->y + r1->h - 1;
- int xf2 = r2->x + r2->w - 1;
- int yf2 = r2->y + r2->h - 1;
-
- set_color_bk();
-
- /* left */
- if (r1->x > r2->x)
- rectfi(r2->x, r2->y, r1->x - 1, yf2);
-
- /* right */
- if (xf1 < xf2)
- rectfi(xf1 + 1, r2->y, xf2, yf2);
-
- /* bottom */
- if (r1->y > r2->y)
- rectfi(r1->x - 1, r2->y, xf1 + 1, r1->y - 1);
-
- /* top */
- if (yf1 < yf2)
- rectfi(r1->x - 1, yf1 + 1, xf1 + 1, yf2);
- }
-
- /******************************************************************
- * Clear the regions outside a rectangle and clips at the window
- * boundary. Could be implemented as clear_between_rect.
- ******************************************************************/
- void
- clear_outside_rect(const Rect_t * r)
- {
- int xf = r->x + r->w - 1;
- int yf = r->y + r->h - 1;
-
- set_color_bk();
-
- /* left */
- if (r->x > 0)
- rectfi(0, 0, r->x - 1, win_h - 1);
-
- /* right */
- if (xf < win_w - 1)
- rectfi(xf + 1, 0, win_w - 1, win_h - 1);
-
- /* bottom */
- if (r->y > 0)
- rectfi(r->x - 1, 0, xf + 1, r->y - 1);
-
- /* top */
- if (yf < win_h - 1)
- rectfi(r->x - 1, yf + 1, xf + 1, win_h - 1);
- }
-
-
- /***************************************************************
- * Set current color.
- ***************************************************************/
- void
- Color(rgba_t col, int ci)
- {
- if (rgbmode)
- cpack(col);
- else
- color(ci);
- }
-
- /*****************************************************************
- * Color is given as 4 element array: the first three are RGB
- * and the fourth is CI
- ****************************************************************/
- void
- Color4(int *c)
- {
- if (rgbmode)
- cpack(Pack(c[0], c[1], c[2]));
- else
- color(c[3]);
- }
-
- /***************************************************************
- * activate current background color
- ***************************************************************/
- void
- set_color_bk(void)
- {
- Color(bkcolor, bkindex);
- }
-
- /*********************************************************
- * Clear a rectanglular region to current bk color
- ********************************************************/
- void
- rect_clear(long win, int xi, int xf, int yi, int yf)
- {
- set_current_window(win);
- viewport(xi, xf, yi, yf);
- clear_it();
- }
-
- /*********************************************************
- * Pixel blind rectwrite. Should not be called by any of
- * of the displaying related routines, it is meant for
- * subimage handling
- ********************************************************/
-
- void
- Rectwrite(int xi, int yi, int xf, int yf, void *r)
- {
-
- frontbuffer(1);
-
- if (rgbmode)
- lrectwrite(xi, yi, xf, yf, r);
- else
- rectwrite(xi, yi, xf, yf, r);
-
- frontbuffer(!double_buf);
-
- }
-
- /****************************************************************
- * Pixel type blind framebuffer read
- ***************************************************************/
- long
- Rectread(int xi, int yi, int xf, int yf, void *r)
- {
- return rgbmode ?
- lrectread(xi, yi, xf, yf, r) : rectread(xi, yi, xf, yf, r);
- }
-
-
- /************************************************************
- * All display related routines, variables
- ************************************************************/
-
- static int pxi, pxf, px0, pyi, pyf, py0;
- static long xy[2];
- static rgba_t **rgba;
- static Colorindex **cind;
- static float zoomx, zoomy;
-
- #define DISP_ROW(y,x1,x2,f,ras) \
- f(x1,y,x2,y,(ras[y+py0] + (x1 + im->xoff1 - pxi )))
-
- /**************************************************************
- * display from top to bottom
- **************************************************************/
-
- static void
- ds_down(IPTR im)
- {
- register int j;
-
- if (IS_CPACK(im))
- {
- for (j = pyf; j >= pyi; j--)
- DISP_ROW(j, pxi, pxf, lrectwrite, rgba);
- }
- else
- {
- for (j = pyf; j >= pyi; j--)
- DISP_ROW(j, pxi, pxf, rectwrite, cind);
- }
- }
-
- /*************************************************************
- * display from bottom to top
- ************************************************************/
-
- static void
- ds_up(IPTR im)
- {
- register int j;
-
- if (IS_CPACK(im))
- {
- for (j = pyi; j <= pyf; j++)
- DISP_ROW(j, pxi, pxf, lrectwrite, rgba);
- }
- else
- {
- for (j = pyi; j <= pyf; j++)
- DISP_ROW(j, pxi, pxf, rectwrite, cind);
- }
- }
-
- /************************************************************************
- * Default. Write pixels in one scoop
- ************************************************************************/
-
- static void
- ds_block(IPTR im)
- {
- if (zoomx > 1.1 || zoomy > 1.1)
- {
- if (IS_CPACK(im))
- lrectwrite(im->xi, im->yi, im->xi + im->w - 1,
- im->yi + im->h - 1, rgba[0]);
- else
- rectwrite(im->xi, im->yi, im->xi + im->w - 1,
- im->yi + im->h - 1, cind[0]);
- return;
- }
-
-
- if (IS_CPACK(im))
- {
-
- if (im->w < (win_w + 400) && im->xoff1 < 400 && im->xoff2 < 400)
- {
- lrectwrite(im->xi, pyi, im->xf, pyf, rgba[im->yoff1]);
- }
- else
- {
- ds_up(im);
- }
- return;
- }
-
- /* must be CI and need to take care of the bug */
-
- #ifdef PWRITE_BUG
- if ((im->xi + win_xo) > 0 && im->xf < getgdesc(GD_XPMAX))
- #else
- if (im->w < (win_w + 400) && im->xoff1 < 400 && im->xoff2 < 400)
- #endif
- {
- rectwrite(im->xi, pyi, im->xf, pyf, cind[im->yoff1]);
- }
- else
- {
- ds_up(im);
- }
-
- }
-
- /************************************************************
- * explode from center to top and bottom
- **************************************************************/
-
- static void
- ds_ctb(IPTR im)
- {
- register int j, hh = (pyf - pyi + 1) / 2, cc = (pyf + pyi) / 2;
-
- if (IS_CPACK(im))
- {
- for (j = 0; j <= hh; j++)
- {
- if (cc - j >= pyi)
- DISP_ROW(cc - j, pxi, pxf, lrectwrite, rgba);
- if (cc + j <= pyf)
- DISP_ROW(cc + j, pxi, pxf, lrectwrite, rgba);
- }
- }
- else
- {
- for (j = 0; j <= hh; j++)
- {
- if (cc - j >= pyi)
- DISP_ROW(cc - j, pxi, pxf, rectwrite, cind);
- if (cc + j <= pyf)
- DISP_ROW(cc + j, pxi, pxf, rectwrite, cind);
- }
- }
- }
-
- /******************************************************************
- * explode from top and bottom towards the center line
- ******************************************************************/
-
- static void
- ds_tbc(IPTR im)
- {
- register int j, hh = (pyf - pyi + 1) / 2;
-
- if (IS_CPACK(im))
- {
- for (j = 0; j <= hh; j++)
- {
- DISP_ROW(pyi + j, pxi, pxf, lrectwrite, rgba);
- DISP_ROW(pyf - j, pxi, pxf, lrectwrite, rgba);
- }
- }
- else
- {
- for (j = 0; j <= hh; j++)
- {
- DISP_ROW(pyi + j, pxi, pxf, rectwrite, cind);
- DISP_ROW(pyf - j, pxi, pxf, rectwrite, cind);
- }
- }
- }
-
- #define DN_RSEG(y1,y2,s,f,ras) \
- do { \
- for (i=y1;i>=y2;i-=s) { DISP_ROW(i,pxi,pxf,f,ras);} \
- } while (ZERO)
-
- /**********************************************************
- * GIF interlace
- **********************************************************/
- static void
- ds_gint(IPTR im)
- {
- register int i;
-
- if (IS_CPACK(im))
- {
- DN_RSEG(pyf, pyi, 8, lrectwrite, rgba);
- DN_RSEG(pyf - 4, pyi, 8, lrectwrite, rgba);
- DN_RSEG(pyf - 2, pyi, 4, lrectwrite, rgba);
- DN_RSEG(pyf - 1, pyi, 2, lrectwrite, rgba);
- }
- else
- {
- DN_RSEG(pyf, pyi, 8, rectwrite, cind);
- DN_RSEG(pyf - 4, pyi, 8, rectwrite, cind);
- DN_RSEG(pyf - 2, pyi, 4, rectwrite, cind);
- DN_RSEG(pyf - 1, pyi, 2, rectwrite, cind);
- }
- }
-
- /*************************************************************
- * nice interlace
- *************************************************************/
-
- static void
- ds_int(IPTR im)
- {
- register int i;
-
- if (IS_CPACK(im))
- {
- DN_RSEG(pyf, pyi, 4, lrectwrite, rgba);
- DN_RSEG(pyf - 2, pyi, 4, lrectwrite, rgba);
- DN_RSEG(pyf - 3, pyi, 4, lrectwrite, rgba);
- DN_RSEG(pyf - 1, pyi, 4, lrectwrite, rgba);
- }
- else
- {
- DN_RSEG(pyf, pyi, 4, rectwrite, cind);
- DN_RSEG(pyf - 2, pyi, 4, rectwrite, cind);
- DN_RSEG(pyf - 3, pyi, 4, rectwrite, cind);
- DN_RSEG(pyf - 1, pyi, 4, rectwrite, cind);
- }
- }
-
-
- #define DISP_COL(x,y1,y2,f,ras) \
- do { \
- register int k_, xx_; \
- xy[0]= x; xx_= x + px0; \
- for (k_ = y1; k_ <= y2; ++k_) { \
- xy[1]= k_; f(ras[k_+py0][xx_]); v2i(xy); \
- } \
- } while (ZERO)
-
-
-
- /*****************************************************************
- * display from left to right
- *****************************************************************/
-
- static void
- ds_left(IPTR im)
- {
- register int i;
-
- bgnpoint();
-
- if (IS_CPACK(im))
- {
- for (i = pxi; i <= pxf; i++)
- DISP_COL(i, pyi, pyf, cpack, rgba);
- }
- else
- {
- for (i = pxi; i <= pxf; i++)
- DISP_COL(i, pyi, pyf, color, cind);
- }
-
- endpoint();
- }
-
- /***************************************************************
- * Display from right to left
- ***************************************************************/
-
- static void
- ds_right(IPTR im)
- {
- register int i;
-
- bgnpoint();
-
- if (IS_CPACK(im))
- {
- for (i = pxf; i >= pxi; i--)
- DISP_COL(i, pyi, pyf, cpack, rgba);
- }
- else
- {
- for (i = pxf; i >= pxi; i--)
- DISP_COL(i, pyi, pyf, color, cind);
- }
-
- endpoint();
- }
-
- #define LR_CSEG(x1,x2,s,f,ras) \
- for ( i= x1; i<= x2; i += s) \
- DISP_COL(i,pyi,pyf,f,ras)
-
-
- /*****************************************************************
- * columnwise interlace
- ******************************************************************/
-
- static void
- ds_cint(IPTR im)
- {
- register int i;
-
- bgnpoint();
-
- if (IS_CPACK(im))
- {
- LR_CSEG(pxi, pxf, 4, cpack, rgba);
- LR_CSEG(pxi + 2, pxf, 4, cpack, rgba);
- LR_CSEG(pxi + 1, pxf, 4, cpack, rgba);
- LR_CSEG(pxi + 3, pxf, 4, cpack, rgba);
- }
- else
- {
- LR_CSEG(pxi, pxf, 4, color, cind);
- LR_CSEG(pxi + 2, pxf, 4, color, cind);
- LR_CSEG(pxi + 1, pxf, 4, color, cind);
- LR_CSEG(pxi + 3, pxf, 4, color, cind);
- }
-
- endpoint();
- }
-
- /***********************************************************
- * explode leftright from center
- ************************************************************/
-
- static void
- ds_clr(IPTR im)
- {
- register int i, ww = (pxf - pxi + 1) / 2, cc = (pxf + pxi) / 2;
-
- bgnpoint();
-
- if (IS_CPACK(im))
- {
- for (i = 0; i <= ww; i++)
- {
- if (cc - i >= pxi)
- DISP_COL(cc - i, pyi, pyf, cpack, rgba);
- if (cc + i <= pxf)
- DISP_COL(cc + i, pyi, pyf, cpack, rgba);
- }
- }
- else
- {
- for (i = 0; i <= ww; i++)
- {
- if (cc - i >= pxi)
- DISP_COL(cc - i, pyi, pyf, color, cind);
- if (cc + i <= pxf)
- DISP_COL(cc + i, pyi, pyf, color, cind);
- }
- }
-
- endpoint();
- }
-
- /************************************************************
- * explode left right towards the center
- ************************************************************/
-
- static void
- ds_lrc(IPTR im)
- {
- register int i, ww = (pxf - pxi + 1) / 2;
-
- bgnpoint();
-
- if (IS_CPACK(im))
- {
- for (i = 0; i <= ww; i++)
- {
- DISP_COL(pxi + i, pyi, pyf, cpack, rgba);
- DISP_COL(pxf - i, pyi, pyf, cpack, rgba);
- }
- }
- else
- {
- for (i = 0; i <= ww; i++)
- {
- DISP_COL(pxi + i, pyi, pyf, color, cind);
- DISP_COL(pxf - i, pyi, pyf, color, cind);
- }
- }
-
- endpoint();
- }
-
- /* macros that displays rectangularly towards the center */
- #define RDISP_RECT(x1,y1,x2,y2,rf,cf,ras) \
- do { \
- DISP_ROW(y1,x1,x2,rf,ras); \
- DISP_ROW(y2,x1,x2,rf,ras); \
- bgnpoint(); \
- DISP_COL(x1,y1,y2,cf,ras); \
- DISP_COL(x2,y1,y2,cf,ras); \
- endpoint(); \
- } while (ZERO)
-
-
- /*****************************************************************
- * Display rectangularly
- *****************************************************************/
-
- static void
- ds_rec1(IPTR im)
- {
- register int m = 0, hh = (pyf - pyi + 1) / 2, ww = (pxf - pxi + 1) / 2;
- register int xx1 = pxi, xx2 = pxf, yy1 = pyi, yy2 = pyf;
-
- if (IS_CPACK(im))
- {
- do
- {
- RDISP_RECT(xx1, yy1, xx2, yy2, lrectwrite, cpack, rgba);
- xx1++;
- yy1++;
- xx2--;
- yy2--;
- m++;
- }
- while (m <= hh || m <= ww);
- }
- else
- {
- do
- {
- RDISP_RECT(xx1, yy1, xx2, yy2, rectwrite, color, cind);
- xx1++;
- yy1++;
- xx2--;
- yy2--;
- m++;
- }
- while (m <= hh || m <= ww);
- }
- }
-
- /*************************************************************
- * display rectangularly from the center
- **************************************************************/
-
- static void
- ds_rec2(IPTR im)
- {
- int ch = (pyf + pyi) / 2, cw = (pxf + pxi) / 2;
- register int m = 0, hh = (pyf - pyi + 1) / 2, ww = (pxf - pxi + 1) / 2;
- register int xx1 = cw, xx2 = cw, yy1 = ch, yy2 = ch;
-
- if (IS_CPACK(im))
- {
- do
- {
- RDISP_RECT(xx1, yy1, xx2, yy2, lrectwrite, cpack, rgba);
- xx1 = (xx1 <= pxi) ? pxi : xx1 - 1;
- yy1 = (yy1 <= pyi) ? pyi : yy1 - 1;
- xx2 = (xx2 >= pxf) ? pxf : xx2 + 1;
- yy2 = (yy2 >= pyf) ? pyf : yy2 + 1;
- m++;
- }
- while (m <= hh || m <= ww);
- }
- else
- {
- do
- {
- RDISP_RECT(xx1, yy1, xx2, yy2, rectwrite, color, cind);
- xx1 = (xx1 <= pxi) ? pxi : xx1 - 1;
- yy1 = (yy1 <= pyi) ? pyi : yy1 - 1;
- xx2 = (xx2 >= pxf) ? pxf : xx2 + 1;
- yy2 = (yy2 >= pyf) ? pyf : yy2 + 1;
- m++;
- }
- while (m <= hh || m <= ww);
- }
- }
-
- /************************************************************
- * blend two streams: c = s * a + ( 1 - s) * b
- ***********************************************************/
-
- static int blend_buf[2 * PCMAX + 3];
-
- static void
- blend_mat(register rgba_t *c, register rgba_t *a, register rgba_t *b,
- register long total, register float s)
- {
- register int r1, g1, b1;
- register int r2, g2, b2;
- register int r3, g3, b3;
- register rgba_t *cs;
- register int *lut = blend_buf;
- int i;
-
- /* calculate the lookup table */
-
- lut += PCMAXV;
- for (i = -PCMAXV; i < PCMAX; i++)
- lut[i] = (s * i);
-
- /* blend */
- for (cs = c + total; c < cs; c++, a++, b++)
- {
- Unpack(*a, r1, g1, b1);
- Unpack(*b, r2, g2, b2);
- r3 = *(lut + r1 - r2) + r2;
- g3 = *(lut + g1 - g2) + g2;
- b3 = *(lut + b1 - b2) + b2;
- *c = Pack(r3, g3, b3);
- }
- }
-
- /****************************************************************
- * slowly fade into new picture
- ****************************************************************/
-
- static void
- ds_fade(IPTR im)
- {
- rgba_t **old, **new, **blend;
- int nstep = 25;
- float f, df;
- const Rect_t *ir, *wr, *ur;
-
- /* fade can only be done to RGB images */
- if (IS_CI(im))
- {
- ds_block(im);
- return;
- }
-
- /* find the dimension of exposed part of the image */
- wr = make_rect(0, 0, win_w - 1, win_h - 1);
- ur = union_rect(ir = img_rect(im), wr);
-
-
- /* grab all the memory we needed before proceed */
-
- if (!(old = get_mat(ur->h, ur->w, sizeof(rgba_t))))
- {
- ds_block(im);
- return;
- }
-
-
- /* get the current image on screen */
- lrectread(ur->x, ur->y, ur->x + ur->w - 1, ur->y + ur->h - 1, old[0]);
-
- /*
- * matrix for new image: if the new image is completely exposed, no need
- * to allocate a matrix for the exposed part
- */
- new = (equal_rect(ir, ur) ? im->mraster :
- get_subimage(im, ur->x, ur->y, ur->w, ur->h));
-
- if (!new)
- {
- ds_block(im);
- return;
- }
-
- blend = get_mat(ur->h, ur->w, sizeof(rgba_t));
-
- /* adjust steps: if image is large, decrease nstep, otherwise too slow */
-
- nstep = (1600.0 / (im->h + im->w) * nstep);
-
- df = 1.0 / nstep;
-
-
- /* write the first (0) blend immediately, looks faster */
- set_current_window(win_id);
- clear_outside_rect(ur);
- lrectwrite(ur->x, ur->y, ur->x + ur->w - 1, ur->y + ur->h - 1, old[0]);
- frontbuffer(0);
-
- /* simply blend the two images: b = a * old + (1-a) * new */
- for (f = 1.0 - df; f >= 0.0; f -= df)
- {
- blend_mat(blend[0], old[0], new[0], ur->w * ur->h, f);
- lrectwrite(ur->x, ur->y,
- ur->x + ur->w - 1, ur->y + ur->h - 1, blend[0]);
- swapbuffers();
- check_emergency();
- }
-
- /*
- * need to do this to show the complete pictures as blending might have
- * errors due to floating point operation
- */
-
- ds_block(im);
-
- free_mat(blend);
- free_mat(old);
-
- if (new != im->mraster)
- free_mat(new);
- }
-
- /************************************************************
- * Spark fade
- ***********************************************************/
-
- static short *msparkle;
- static int max_sp;
-
- /** Load sparkle data. should generate this on the fly .... ***/
- static int
- load_sparkle(void)
- {
- FILE *fp = get_HELPfile_fp("sparkle.dat", "r");
- int mm;
- short aa;
- static int warned;
-
- if (!fp)
- {
- if (!warned)
- {
- Bark("LoadSPData", "BadOpen");
- warned = 1;
- }
- return -1;
- }
-
- fread(&aa, sizeof(short), 1, fp);
- max_sp = aa;
- mm = max_sp * max_sp;
- msparkle = malloc(sizeof(short) * (mm + 1));
- fread(msparkle, sizeof(short), mm, fp);
- (void) fclose(fp);
- return 0;
- }
-
- /************************************************************
- * Actually do the sparkle fade
- ************************************************************/
-
- static void
- ds_sprkl(IPTR im)
- {
- static int first = 1;
- register int cellx, celly;
- register int i1, j1, xx1, xx2, yy1, yy2;
- register int i;
-
- if (first)
- first = load_sparkle();
-
- if (first || !msparkle)
- {
- ds_block(im);
- return;
- }
-
- cellx = im->w / max_sp + ((im->w % max_sp) != 0);
- celly = im->h / max_sp + ((im->h % max_sp) != 0);
-
- for (i = 0; i < (max_sp * max_sp); i++)
- {
- i1 = msparkle[i] / max_sp;
- j1 = msparkle[i] % max_sp;
- xx1 = im->xi + i1 * cellx;
- yy1 = im->yi + j1 * celly;
- xx2 = xx1 + cellx;
- yy2 = yy1 + celly;
- if (xx2 > im->xf)
- xx2 = im->xf;
- if (yy2 > im->yf)
- yy2 = im->yf;
- if (xx2 > xx1 && yy2 > yy1)
- draw_subimage(im, xx1, yy1, xx2 - xx1 + 1, yy2 - yy1 + 1);
- }
- }
-
- /******************************************************************
- * If image is larger than screen or its position not conform to the
- * positioning requirememt, this routine will be called.
- *****************************************************************/
-
- static void
- positioning_image(IPTR im)
- {
-
- im->xoff1 = (im->xi < 0) ? -im->xi : 0;
- im->xoff2 = (im->xf > win_w) ? (win_w - im->xf - 1) : 0;
- im->yoff1 = (im->yi < 0) ? -im->yi : 0;
- im->yoff2 = (im->yf > win_h) ? (win_h - im->yf - 1) : 0;
-
- #ifdef MTRACE
- M_trace("PosImg", "xoff1=%d yoff1=%d", im->xoff1, im->yoff1);
- #endif
- }
-
- /************* checks if position is ok ****************************/
-
- static int
- bad_position(IPTR im)
- {
-
- return ((im->xoff1 != 0 && (im->xoff1 + im->xi) != 0) ||
- (im->yoff1 != 0 && (im->yoff1 + im->yi) != 0) ||
- (im->xoff2 != 0 && (im->xoff2 + im->xf) != win_w - 1) ||
- (im->yoff2 != 0 && (im->yoff2 + im->yf) != win_h - 1));
- }
-
- /*****************************************************************
- * the global display function interface
- *
- *****************************************************************/
- typedef enum
- {
- DS_INVALID = -1, /* forcing type to be of a signed type */
- DS_BLOCK,
- DS_DOWN,
- DS_UP,
- DS_LEFT,
- DS_RIGHT,
- DS_TBC,
- DS_CTB,
- DS_LRC,
- DS_CLR,
- DS_INT,
- DS_CINT,
- DS_GINT,
- DS_REC1,
- DS_REC2,
- DS_SPRKL,
- DS_FADE,
- DS_CYC /* special: cyclr thru all of above */
- } DS_MODE;
-
- typedef struct
- {
- DS_MODE ds;
- void (*dsfunc) (IPTR);
- }
- Disp;
-
- static Disp disp[] =
- {
- {DS_BLOCK, ds_block},
- {DS_DOWN, ds_down},
- {DS_UP, ds_up},
- {DS_LEFT, ds_left},
- {DS_RIGHT, ds_right},
- {DS_TBC, ds_tbc},
- {DS_CTB, ds_ctb},
- {DS_LRC, ds_lrc},
- {DS_CLR, ds_clr},
- {DS_INT, ds_int},
- {DS_CINT, ds_cint},
- {DS_GINT, ds_gint},
- {DS_REC1, ds_rec1},
- {DS_REC2, ds_rec2},
- {DS_SPRKL, ds_sprkl},
- {DS_FADE, ds_fade}
- };
-
- static int ndisp = sizeof(disp) / sizeof(disp[0]);
-
- /****** funciton generates the option string *******/
- const char *
- gds_string(void)
- {
- return "Block|Down|Up|Left|Right|DownUp|UpDown|LR|RL|Int|CInt|"
- "GInt|Rec1|Rec2|Sparkle|Fade|Cycle";
- }
-
- /******************************************************************
- * Display the image defined in the IPTR structure
- *****************************************************************/
-
- static void
- set_display_zoom(IPTR im)
- {
-
- if (g_zoomx < 0.1 || g_zoomy < 0.1)
- {
- zoomx = ((win_w + 100) / im->w);
- zoomy = ((win_h + 100) / im->h);
- zoomx = zoomy = Min(zoomx, zoomy);
- if (zoomx < 0.1)
- zoomx = zoomy = 1.0;
- }
- else
- {
- zoomx = g_zoomx;
- zoomy = g_zoomy;
- }
- }
-
- static int display_auto; /* so we can turn buy cursor off */
- static int dstyle;
-
- static void
- refresh_display(IPTR i)
- {
-
- if (dstyle != DS_FADE && (double_buf || (win_h > i->h || win_w > i->w)))
- clear_outside_rect(img_rect(i));
- }
-
- void
- display_image(IPTR im, int ds_fancy, int pre_clean)
- {
- int ldstyle = ds_fancy;
-
- if (!image_ready(im, "Display"))
- return;
-
- if (!display_auto)
- show_busy("");
-
- #ifdef MDEBUG
- M_debug("DisplayImage", "Setting Mode");
- #endif
-
-
- if (ldstyle < 0 || ldstyle >= ndisp)
- ldstyle = DS_BLOCK;
-
- dstyle = ldstyle; /* center image uses dstyle */
-
- /* Initialize CI&RGBA matrix */
- rgba = im->mraster;
- cind = im->mraster;
-
- set_current_window(win_id);
- reshapeviewport();
- set_display_mode(im);
- set_display_zoom(im);
-
- /* If not centered , center it. */
-
- if (im->w != (im->xf - im->xi + 1) || im->h != (im->yf - im->yi + 1))
- {
- update_image_info(im);
- center_image(im, 2);
- M_info("DisplayImage", "Centering Image");
- }
-
- if (bad_position(im))
- positioning_image(im);
-
- /*
- * avoid repaint screen if possible, also if the display style is fade,
- * must not clear screen
- */
-
- M_info("DisplayImage", "Clearing Display");
-
- if (pre_clean)
- refresh_display(im);
-
-
- pxi = im->xi + im->xoff1;
- pxf = im->xf + im->xoff2;
- px0 = -im->xi;
- pyi = im->yi + im->yoff1;
- pyf = im->yf + im->yoff2;
- py0 = -im->yi;
-
- set_current_window(win_id);
- reshapeviewport();
-
- if (dstyle == DS_BLOCK)
- {
- rectzoom(zoomx, zoomy);
- }
- else
- {
- swapbuffers(); /* show last clear_outside_rect */
- refresh_display(im);
- frontbuffer(1);
- rectzoom(1.0, 1.0);
- }
-
- #ifdef MDEBUG
- M_debug("DisplayImage", "Displaying with style=%d", (int) ldstyle);
- #endif
-
- (disp + ldstyle)->dsfunc(im);
-
- end_busy();
-
- frontbuffer(!double_buf);
-
- }
-
- /******************************************************************
- * Similar to display_image but addtionally display text and
- * other misc. stuff. Also the default display function
- ******************************************************************/
-
- void
- Generic_display(IPTR im, int ds_fancy, int pre_clean)
- {
- static int lfancy; /* counter. Dstyle is the current style */
- long owin = winget();
-
- /*
- * it is possible that main window is not initialized if fit_image_size
- * is requested
- */
-
- open_main_window(im);
-
- #ifdef MTRACE
- M_trace("GenericDisplay", "Entering with ds_fancy=%d", ds_fancy);
- #endif
-
- if (ds_fancy >= ndisp)
- ds_fancy = DS_CYC;
-
- dstyle = (ds_fancy == DS_CYC) ? (++lfancy % ndisp) : ds_fancy;
-
- /* interlace only if image is interlaced and not repaint (-1) */
- if (im->interlace && ds_fancy >= 0)
- dstyle = DS_GINT;
-
- display_image(im, dstyle, pre_clean);
- display_sgf(im);
- display_text(im);
-
- /*
- * if ds_fancy > 0, frontbuffer & backbuffer already consistent as
- * display_image turned frontbuffer true
- */
-
- if (double_buf && dstyle <= 0)
- {
- swapbuffers();
-
- /*
- * in slideshow mode, we do not need to guarantee backbuffer
- * consistency, which is relied upon in Text, C&P only.
- */
-
- if (!slideshow)
- {
- display_auto = 1;
- display_image(im, DS_BLOCK, pre_clean);
- display_sgf(im);
- display_text(im);
- display_auto = 0;
- }
- }
-
- set_current_window(owin);
-
- #ifdef MTRACE
- M_trace("GenericDisplay", "Exiting");
- #endif
- }
-
-
- /************************************************************************
- * xoff and yoff makes displaying large image a little faster. Note
- * im->xf+im->xoff2 - im->xi+im->xoff1 + 1== im->w>win_w?win_w:im->w;
- *
- * xdir:0 for y direction 1 for x direction 3 for both
- ************************************************************************/
-
- void
- center_image(IPTR im, int xdir)
- {
- int w = im->w, h = im->h;
-
- if (dstyle == DS_BLOCK)
- {
- w *= zoomx;
- h *= zoomy;
- }
-
- if (xdir)
- {
- im->xi = (win_w - w) / 2;
-
- #ifdef PWRITE_BUG
- if ((im->xi + win_xo) <= 0)
- im->xi = -win_xo + 1;
- #endif
- im->xf = im->xi + w - 1;
- }
-
- if (xdir == 2 || xdir == 0)
- {
- im->yi = (win_h - h) / 2;
- im->yf = im->yi + h - 1;
- }
-
- #ifdef MDEBUG
- M_debug("CenterImage", "xi=%d yi=%d", im->xi, im->yi);
- #endif
-
- positioning_image(im);
- }
-
- /********************************************************************
- * Pan iamge so that the viewing area is not limited by the screen size.
- * Code is so written to minimize the repaint if single buffer is used.
- ********************************************************************/
-
- /*
- * the buttons are numbered as the keypad
- */
- int
- image_pan(IPTR im, int x, int pstep)
- {
- int xvi[2], xvf[2], yvi[2], yvf[2];
- int nc = 1;
- int xi, xf, yi, yf;
- static int last_center, min_keep = 100;
-
- /*
- * if image not ready, should be silently ignored because the pan button
- * is a touch button
- */
-
- if (!im->ok)
- return -1;
-
-
- xi = xvi[0] = xvi[1] = im->xi;
- xf = xvf[0] = xvf[1] = im->xf;
- yi = yvi[0] = yvi[1] = im->yi;
- yf = yvf[0] = yvf[1] = im->yf;
-
- switch (x)
- {
- case 1: /* left-down */
- nc = 2;
- yvi[0] = yf - pstep;
- xvi[1] = xf - pstep;
- yvf[1] = yf - pstep;
- xi -= pstep;
- yi -= pstep;
- break;
- case 2: /* down */
- yvi[0] = yf - pstep;
- yi -= pstep;
- break;
- case 3:
- nc = 2;
- yvi[0] = yf - pstep;
- xvf[1] = xi + pstep;
- yvf[1] = yf - pstep;
- xi += pstep;
- yi -= pstep;
- break;
- case 4:
- xvi[0] = xf - pstep;
- xi -= pstep;
- break;
- case 5:
- if (!last_center)
- {
- center_image(im, 2);
- xi = im->xi;
- yi = im->yi;
- }
- else
- nc = 0;
- break;
- case 6:
- xvf[0] = xi + pstep;
- xi += pstep;
- break;
- case 7:
- nc = 2;
- yvf[0] = yi + pstep;
- xvi[1] = xf - pstep;
- yvi[1] = yi + pstep;
- xi -= pstep;
- yi += pstep;
- break;
- case 8:
- yvf[0] = yi + pstep;
- yi += pstep;
- break;
- case 9:
- nc = 2;
- yvf[0] = yi + pstep;
- yvi[1] = yi + pstep;
- xvf[1] = xi + pstep;
- xi += pstep;
- yi += pstep;
- break;
- default:
- Bark("ImagePan", bugquit); /* something is very wrong */
- clean_up();
- break;
- }
-
- if (nc)
- {
- xf = xi + im->w - 1;
- yf = yi + im->h - 1;
- if (xf < min_keep)
- {
- xf = min_keep;
- xi = xf - im->w + 1;
- }
-
- if (xi > win_w - min_keep)
- {
- xi = win_w - min_keep;
- xf = xi + im->w - 1;
- }
-
- if (yf < min_keep)
- {
- yf = min_keep;
- yi = yf - im->h + 1;
- }
-
- if (yi > win_h - min_keep)
- {
- yi = win_h - min_keep;
- yf = yi + im->h - 1;
- }
-
- im->xi = xi;
- im->xf = xf;
- im->yi = yi;
- im->yf = yf;
- positioning_image(im);
-
- if (!(xi < 0 && yi < 0 && xf > win_w && yf > win_w))
- {
- rect_clear(win_id, xvi[0], xvf[0], yvi[0], yvf[0]);
- if (nc > 1)
- rect_clear(win_id, xvi[1], xvf[1], yvi[1], yvf[1]);
- }
-
- display_auto = 1;
- im->io->display(im, -1, double_buf);
- display_auto = 0;
- }
-
- last_center = (x == 5);
-
- handle_wm_other(im);
- fl_qenter(KEYBD, 2);
-
- return 0;
- }
-
- /********************************************************************
- * Auto pan
- *******************************************************************/
-
- #define PAN_CRIT 20 /* unviewable less than this is ignored */
-
- void
- auto_pan(IPTR im)
- {
- int dist, dist1, dist2, pstep;
- int saveflag = always_clear;
-
- if ((im->w - PAN_CRIT) < win_w && (im->h - PAN_CRIT) < win_h)
- return;
-
- /* pan only if requestd or in slides show */
- if (always_pan == 0 || !(slideshow && always_pan == 1))
- return;
-
- msleep(500); /* take a look at it */
- display_auto = 1; /* turn busy cursor off */
- pstep = 4; /* smaller steps looks nicer */
- always_clear = 0; /* do not clear screen */
-
- dist1 = Abs(im->xoff1);
- dist2 = Abs(im->xoff2);
-
- for (dist = dist1; dist > 0; dist -= pstep)
- image_pan(im, 6, pstep);/* move right */
-
- check_emergency(); /* service any Q event */
-
- msleep(500);
-
- for (dist = dist1 + dist2; dist > 0; dist -= pstep)
- image_pan(im, 4, pstep);/* move left */
-
- check_emergency();
- msleep(500);
-
- for (dist = dist2; dist > 0; dist -= pstep)
- image_pan(im, 6, pstep);/* move right */
-
- check_emergency();
- msleep(500);
-
- /* image now is at about the same postion as before */
- dist1 = Abs(im->yoff1);
- dist2 = Abs(im->yoff2);
- for (dist = dist1; dist > 0; dist -= pstep)
- image_pan(im, 8, pstep);/* move up */
-
- check_emergency();
-
- for (dist = dist1 + dist2; dist > 0; dist -= pstep)
- image_pan(im, 2, pstep);/* move down */
-
- check_emergency();
- msleep(500);
-
- /* the corner still not seen, forget it */
- for (dist = dist2; dist > 0; dist -= 2 * pstep)
- image_pan(im, 8, 2 * pstep); /* move up */
-
- /* center both dir */
- image_pan(im, 5, 10);
- display_auto = 0;
- always_clear = saveflag;
- }
-
- #if 0 /* No longer used **{* */
- /*************************************************************
- * Rectcopy is similar to rectcopy except that it optionally
- * does raster move in core image. However, zooming is
- * not obeyed.
- ************************************************************/
-
- static int rascp;
-
- void
- set_rectcp_ras(int y)
- {
- rascp = y;
- }
-
- void
- Rectcopy(int xi, int yi, int xf, int yf, int nx, int ny)
- {
- IPTR im = imgptr;
- void *pp;
- Rect_t des, src;
- const Rect_t *ir, *uu;
-
- frontbuffer(1);
- rectcopy(xi, yi, xf, yf, nx, ny);
- frontbuffer(!double_buf);
-
- if (rascp)
- {
- int w, h;
-
- ir = img_rect(im);
-
- /* the src raster: clip to the image boundary */
- if (!(uu = union_rect(make_rect(xi, yi, xf - xi + 1, yf - yi + 1), ir)))
- return;
- copy_rect(&src, uu);
-
- /* find destination, taking into account of src clipping */
- nx += (src.x - xi);
- ny += (src.y - yi);
-
- copy_rect(&des, make_rect(nx, ny, src.w, src.h));
-
- /* clip to the image boundary */
- if (!(uu = union_rect(&des, ir)))
- return;
- copy_rect(&des, uu);
-
- w = Min(src.w, des.w);
- h = Min(src.h, des.h);
- des.w = src.w = w;
- des.h = src.h = h;
-
- if ((pp = get_subimage(im, src.x, src.y, src.w, src.h)))
- {
- put_subimage(im, pp, &des, 1);
- free_mat(pp);
- }
- }
- }
-
- #endif /* disabling Rectcopy } */
-
- /**********************************************************
- * allow only certain number of bits in raster. This is necessary
- * because the raster might come from framebuffer read, which
- * is 12bits on most machines while CMAPBITS is less than 12
- ************************************************************/
-
- void
- do_ci_mask(register ci_t *ras, unsigned total,
- register unsigned int mask)
- {
- register ci_t *rs = ras + total;
- int m = power_of_2(mask);
-
- /* need to make sure that mask is full bits */
- mask = (m > MAXCML ? MAXCML : m) - 1;
- for (; ras < rs; ras++)
- *ras &= mask;
- }
-
- /*
- * intended primarily to read the main screen
- */
- int
- read_screen(IPTR im, int x, int y, int w, int h)
- {
- long owin = winget();
-
- M_info("ReadScr", "Performing screen read");
- im->xi = x;
- im->yi = y;
- im->xf = im->xi + w - 1;
- im->yf = im->yi + h - 1;
- im->w = w;
- im->h = h;
- set_current_window(win_id);
- reshapeviewport();
- im->ok = (img_get_rastermem(im) < 0) ? 0 :
- Rectread(im->xi, im->yi, im->xf, im->yf, im->raster) > 0;
- set_current_window(owin);
- return im->ok;
- }
-